package com.byron.media.server.sessions;

import com.byron.media.server.enums.MediaType;
import com.byron.media.server.model.DataFactory;
import com.byron.media.server.model.MediaData;
import com.byron.media.server.model.SeqFactory;

import java.util.HashSet;
import java.util.Queue;
import java.util.Set;
import java.util.concurrent.ConcurrentLinkedQueue;

/**
 * 组员
 */
public class Group {

    /**
     * 该组的组名
     */
    private String groupName;

    /**
     * 该组拥有的连接
     */
    private Set<ISession> sessions = new HashSet<>();

    private Set<ISession> readySessionSet = new HashSet<>();       // 准备要加入的队列

    private Set<ISession> leavingSessionSet = new HashSet<>();       // 准备要退出的队列

    private Queue<MediaData> iframeQueue = new ConcurrentLinkedQueue<>();           // i帧的队列

    public Group(String groupName) {
        this.groupName = groupName;
    }

    /**
     * 将session添加到组中
     * @param sessionName
     * @param session
     */
    public void addToGroup(long sessionName, ISession session){
        synchronized (this){
            readySessionSet.add(session);
        }
    }


    /**
     * 从组中删除session
     * @param sessionName
     * @param session
     */
    public void removeFromGroup(long sessionName, ISession session){
        synchronized (this){
            leavingSessionSet.add(session);

            if(leavingSessionSet.size() >= readySessionSet.size() + sessions.size()){
                cleanIframe();
                releaseSelf();
            }
        }
    }

    /**
     * 检查在线信息
     */
    private void checkOnline(){
        if(!readySessionSet.isEmpty()){
            synchronized (this){
                for(ISession s : readySessionSet){
                    sessions.add(s);
                }
                readySessionSet.clear();
            }
        }

        if(!leavingSessionSet.isEmpty()){
            synchronized (this){
                for(ISession s : leavingSessionSet){
                    // 添加到在线
                    sessions.remove(s);
                }
                leavingSessionSet.clear();
            }
        }

        // 最后一个session退出，则销毁group
        if(sessions.isEmpty()){
            cleanIframe();
            releaseSelf();
            return;
        }
    }


    /**
     * 向该组
     * @param fromSessionName
     * @param mediaData
     */
    public void sendToOthers(byte lastServerId, Long fromSessionName, MediaData mediaData){

        checkOnline();

        mediaData.setSeq(SeqFactory.getInstance().generalSeq());
        sessions.forEach(s -> {
            // 添加到在线
            if(s.getSessionName() != fromSessionName){
                s.write(lastServerId, fromSessionName, mediaData);
            }
        });

        pushLastIFrame(mediaData);

    }

    /**
     * 释放自己
     */
    private void releaseSelf() {
        SessionContainer.getInstance().removeGroup(this);
    }


    /**
     * 清除i帧信息
     */
    private void cleanIframe() {
        iframeQueue.clear();
    }


    /**
     * 将组里面的I帧信息推送到前端，用于界面恢复
     */
    private void pushLastIFrame(MediaData data){
        boolean isIframe = MediaType.isIframe(data);
        if(isIframe) {
            Queue<MediaData> freeData = new ConcurrentLinkedQueue<>(iframeQueue);
            iframeQueue.clear();
            DataFactory.getInstance().offerDataBatch(freeData);
        }
        iframeQueue.add(data);
        data.setUsing(true);
    }


    /**
     * 发送最后的I帧信息
     * @param session
     */
    public void sendLastIframe(ISession session) {
        Queue<MediaData> freeData = new ConcurrentLinkedQueue<>(iframeQueue);
        freeData.forEach(data -> session.write((byte)0, 0L, data));
    }

    /**
     * 获取组名字
     */
    public String getGroupName() {
        return groupName;
    }
}
